In this lesson we will consider the java.io package which supports Java's input and output including standard I/O devices and files.
In previous lections we used I/O in almost all examples. When we need to print some information to a console we use methods print() and println() in the System class. This methods only useful for console-based applications. But not all the Java programs work with the console. They may use files and networks.
Java programs perform I/O through streams. A stream is an abstraction that either produces or consumes information. Input stream can abstract many different kinds of input: from a disk file, a keyboard, or a network socket. Likewise, an output stream may refer to the console, a disk file, or a network connection. Java implements streams within class hierarchies defined in the java.io package.
There are two different types of streams defined by Java - byte stream and characters stream.
Byte streams provide a convenient means for handling input and output of bytes. Byte streams are used when reading or writing binary data.
Characters streams provide a convenient means for handling input and output of characters. They use Unicode. Also, in some cases, character streams are more efficient than byte streams.
At the lowest level, all I/O is still byte-oriented. The character-based streams simply provide a convenient and efficient means for handling characters.
Byte streams are defined by using two class hierarchies. At the top are two abstract classes: InputStream and OutputStream. Each of these abstract classes has several concrete subclasses that handle the differences among various devices, such as disk files, network connections, and even memory buffers.
The two most important methods that other classes should implement: read() and write(), which, respectively, read and write bytes of data. Each has a form that is abstract and must be overridden by derived stream classes.
Character streams are defined by using two class hierarchies. At the top are two abstract classes: Reader and Writer. These abstract classes handle Unicode character streams. The character stream classes in java.io are shown below:
The abstract classes Reader and Writer define several key methods that the other stream classes implement. Two of the most important methods are read() and write(), which read and write characters of data, respectively.
All Java programs automatically import the java.lang package. This package defines a class called System, which contains three predefined stream variables: in, out, and err. These fields are declared as public, static, and final within System. This means that they can be used by any other part of your program and without reference to a specific System object.
class System {
private static PrintStream out = new ();
}
class PrintStream {
public void println(String);
}
System.out.println("sdad");
System.out refers to the standard output stream. By default, this is the console. System.in refers to standard input, which is the keyboard by default. System.err refers to the standard error stream, which also is the console by default. However, these streams may be redirected to any compatible I/O device.
System.in is an object of type InputStream; System.out and System.err are objects of type PrintStream. These are byte streams, even though they are typically used to read and write characters from and to the console.
In first versions of Java the only way to perform console input was to use a byte stream. Today, using a byte stream to read console input is still acceptable. However, the preferred method of reading console input is to use a character-oriented stream.
In Java, console input is accomplished by reading from System.in. A commonly used constructor is shown here:
BufferedReader supports a buffered input stream. A commonly used constructor is shown here:
BufferedReader(Reader inputReader)
Here, inputReader is the stream that is linked to the instance of BufferedReader that is being created. Reader is an abstract class. One of its concrete subclasses is InputStreamReader, which converts bytes to characters. To obtain an InputStreamReader object that is linked to System.in, use the following constructor: InputStreamReader(InputStream inputStream)
Because System.in refers to an object of type InputStream, it can be used for constructing InputStreamReader.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Now we constructed a new BufferedReader object and we are able to read data from the console via method int read().
reader.read();
reader.read();
reader.read();
reader.read();
reader.read();
reader.read();
Each time that read( ) is called, it reads a character from the input stream and returns it as an integer value. It returns –1 when an attempt is made to read at the end of the stream.
class BuffReaderDemo {
public static void main(String... args) throws IOException {
char c;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter characters. 'q' will interrupt the program");
do {
c = (char)bufferedReader.read();
System.out.println(c);
} while (c != 'q');
}
}
BuffReaderDemo.main();
To read a string from the keyboard, use the version of readLine() that is a member of the BufferedReader class. Its general form: String readLine() throws IOException
class BuffReaderReadlinesDemo {
public static void main(String... args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = "";
System.out.println("Enter lines of text or 'exit' to quit()");
while (!str.equals("exit")) {
str = br.readLine();
System.out.println(str);
}
}
}
BuffReaderReadlinesDemo.main();
class ReadStringsDemo {
String[] strings = new String[100];
public static void main(String[] args) throws IOException {
ReadStringsDemo o = new ReadStringsDemo();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (int i = 0; i < o.strings.length; i++) {
System.out.println("Enter a line.");
System.out.println("Enter 'stop' to exit");
String input = in.readLine();
if (input.equals("stop")) break;
o.strings[i] = input;
}
System.out.println("The content of array:");
for (int i = 0; i < o.strings.length; i++) {
if (o.strings[i] != null)
System.out.println(o.strings[i]);
}
}
}
Java provides a number of classes and methods that allow you to read and write files. Two of the most often-used stream classes are FileInputStream and FileOutputStream, which create byte streams linked to files. To open a file, you simply create an object of one of these classes, specifying the name of the file as an argument to the constructor. Although both classes support additional constructors, the following are the forms that we will be using:
FileInputStream(String fileName) throws FileNotFoundException
FileOutputStream(String fileName) throws FileNotFoundException
Here, fileName specifies the name of the file that you want to open. When you create an input stream, if the file does not exist, then FileNotFoundException is thrown. For output streams, if the file cannot be opened or created, then FileNotFoundException is thrown.
When you are done with a file, you must close it. This is done by calling the close( ) method, which is implemented by both FileInputStream and FileOutputStream.
To read from a file, you can use a version of read( ) that is defined within FileInputStream. The one that we will use is shown here:
int read( ) throws IOException
Each time that it is called, it reads a single byte from the file and returns the byte as an integer value. read( ) returns –1 when an attempt is made to read at the end of the stream. It can throw an IOException.
To write to a file, you can use the write( ) method defined by FileOutputStream. Its simplest form is shown here:
void write(int byteval) throws IOException
This method writes the byte specified by byteval to the file. Although byteval is declared as an integer, only the low-order eight bits are written to the file. If an error occurs during writing, an IOException is thrown.
In the preceding section, the example programs have made explicit calls to close( ) to close a file once it is no longer needed. After Java 7 there is another more convenient way to close the file. This feature, sometimes referred to as automatic resource management.
Automatic resource management is based on an expanded form of the try statement. Here is its general form:
try (Resourse to open/close) {
// body
} catch (Exception to catch)
Typically, resource-specification is a statement that declares and initializes a resource, such as a file stream. It consists of a variable declaration in which the variable is initialized with a reference to the object being managed. When the try block ends, the resource is automatically released.
The try-with-resources statement can be used only with those resources that implement the AutoCloseable interface defined by java.lang. This interface defines the close( ) method.
try (FileOutputStream fos = new FileOutputStream("myNewFile.txt")) {
fos.write(88);
fos.write(89);
fos.write(90);
} catch (IOException e) {
}